
#ifndef _BYTE_FLOW_GL_UTILS_H_
#define _BYTE_FLOW_GL_UTILS_H_

#include <GLES3/gl3.h>
#include <string>
#include "EGLMacro.h"

#define SHADER_TO_STRING(s) #s

#define MATH_PI 3.1415926535897932384626433832802

#define DEBUG_SAVE_RENDER_TO_PIC 1

#define SELF_NAME(tag) #tag
#define SELF_NAME2(tag) SELF_NAME(tag)
#define SELF_NAME_LINE(tag) "TAG[" SELF_NAME2(tag)"],LINE[" SELF_NAME2(__LINE__)"]"
#define FUNC_LINE __FUNCTION__,__LINE__

#ifdef DEBUG_SAVE_RENDER_TO_PIC
#define SAVE_RENDER GLUtils::saveRender
#else
#define SAVE_RENDER //
#endif



class GLUtils {
public:
    static GLuint LoadShader(GLenum shaderType, const char *pSource);

    static GLuint CreateProgram(const char *pVertexShaderSource, const char *pFragShaderSource,
                                GLuint &vertexShaderHandle,
                                GLuint &fragShaderHandle);

    static GLuint CreateProgram(const char *pVertexShaderSource, const char *pFragShaderSource);

    static GLuint CreateProgramWithFeedback(
            const char *pVertexShaderSource,
            const char *pFragShaderSource,
            GLuint &vertexShaderHandle,
            GLuint &fragShaderHandle,
            const GLchar **varying,
            int varyingCount);

    static void DeleteProgram(GLuint &program);

    static void CheckGLError(const char *pGLOperation);

    static void setBool(GLuint programId, const std::string &name, bool value) {
        glUniform1i(glGetUniformLocation(programId, name.c_str()), (int) value);
    }

    static void setInt(GLuint programId, const std::string &name, int value) {
        glUniform1i(glGetUniformLocation(programId, name.c_str()), value);
    }

    static void setFloat(GLuint programId, const std::string &name, float value) {
        glUniform1f(glGetUniformLocation(programId, name.c_str()), value);
    }

    static int getThreadId();
    static bool save(const std::string& fileName,int m_width, int m_height,void *m_pixelData, const std::string& fileFormat);

    static bool saveRender(const std::string& tag,int w, int h,const char* func_name, int line);
    static bool savePicture(const std::string& tag,int m_width, int m_height,void *m_pixelData,std::string func_name, int line);
    static unsigned int* createTmpPicture(int width,int height,uint32_t color);
    static unsigned int* createTmpPicture(int width,int height);
    static unsigned int* createTmpPictureEmpty(int width,int height);
    static GLuint createColorfulTexture(int width, int height);
    static GLuint createTexture(int width, int height,uint32_t color);
    static GLuint createTexture(int width, int height,void* data);
//    static void setMat3(GLuint programId, const std::string &name, const mat3 &mat) {
//        glUniformMatrix3fv(glGetUniformLocation(programId, name.c_str()), 1, GL_FALSE, &mat[0][0]);
//    }
//
//    static void setMat4(GLuint programId, const std::string &name, const mat4 &mat) {
//        glUniformMatrix4fv(glGetUniformLocation(programId, name.c_str()), 1, GL_FALSE, &mat[0][0]);
//    }
//
//    static float2 texCoordToVertexCoord(float2 &texCoord) {
//        return float2(2 * texCoord.x - 1, 1 - 2 * texCoord.y, 0);
//    }

};

#endif //